﻿using System;
using Dou.URP;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

namespace Volumes
{
    /// <summary>
    /// 环境阴影
    /// </summary>
    [Serializable, VolumeComponentMenu("VolumeAndFeature/EnvironmentShadow")]
    public class EnvironmentShadow : VolumeComponent, IPostProcessComponent, IVolumeBehaviour
    {
        [InspectorName("固定阴影距离")]
        public BoolParameter fixedDistance = new BoolParameter(false, true);
        [InspectorName("阴影范围(X:镜头最低,Y:镜头最高)")]
        public Vector2Parameter shadowDistanceRange = new Vector2Parameter(new Vector2(100, 300), true);
        [InspectorName("阴影深度偏差")]
        public ClampedFloatParameter depthBias = new ClampedFloatParameter(0.04f, 0f, 10.0f, true);
        [InspectorName("阴影法线偏差")]
        public ClampedFloatParameter normalBias = new ClampedFloatParameter(0.09f, 0f, 10.0f, true);
        
        public bool IsActive() => true;
        public bool IsTileCompatible() => true;
        
        private float _cameraHeight;
        
        public void OnActivate()
        {
            _cameraHeight = Camera.main.transform.position.y;
        }

        public void OnUpdate()
        {
            var pipeline = (UniversalRenderPipelineAsset) GraphicsSettings.currentRenderPipeline;
            
            if (fixedDistance.value)
            {
                pipeline.shadowDistance = shadowDistanceRange.value.x;
            }
            else
            {
                var cameraHeight = Camera.main.transform.position.y;
                if (shadowDistanceRange.overrideState && !Mathf.Approximately(_cameraHeight, cameraHeight))
                {
                    _cameraHeight = cameraHeight;
                    
                    var min = shadowDistanceRange.value.x;
                    var max = shadowDistanceRange.value.y;
                    var rate = (cameraHeight - min) / (max - min);
                    Mathf.Lerp(shadowDistanceRange.value.x, shadowDistanceRange.value.y, rate);
                }
            }
            
            if (depthBias.overrideState)
            {
                pipeline.shadowDepthBias = depthBias.value;
            }
            if (normalBias.overrideState)
            {
                pipeline.shadowNormalBias = normalBias.value;
            }
        }

        public void OnDeactive()
        {
        }
    }
}
